﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Raytracererer
{
    public class Vector3
    {
        public double X; 
        public double Y;
        public double Z;

        public Vector3(double x, double y, double z)
        {
            X = x;
            Y = y;
            Z = z;            
        }
        #region Methods

        public double LengthSquared()
        {
            return Vector3.DotProduct(this, this);
        }
        public double Length()
        {
            return Math.Sqrt(LengthSquared());
        }
        public Vector3 Normalized()
        {
            return Vector3.Scale(this, 1 / Length());
        }
        public override string ToString()
        {
            return "(" + X + ", " + Y + ", " + Z + ")";
        }

        #endregion
        #region Static Methods
        public static Vector3 Add(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
        }
        public static Vector3 Subtract(Vector3 v1, Vector3 v2)
        {
            return Add(v1, Vector3.Scale(v2, -1));
        }
        public static Vector3 Scale(Vector3 v, double scalar)
        {
            return new Vector3(v.X * scalar, v.Y * scalar, v.Z * scalar);
        }
        public static double DotProduct(Vector3 v1, Vector3 v2)
        {
            return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
        }
        public static double CosAngle(Vector3 v1, Vector3 v2)
        {
            return Vector3.DotProduct(v1, v2) / (v1.Length() * v2.Length());
        }
        public static double Angle(Vector3 v1, Vector3 v2)
        {
            return Math.Acos(Vector3.CosAngle(v1, v2));
        }
        public static Vector3 Mirror(Vector3 v1, Vector3 v2)
        {
            return 2 * Vector3.DotProduct(v1,v2) / v2.LengthSquared() * v2 - v1;
        }
        public static Vector3 Cross(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.Y * v2.Z - v1.Z * v2.Y, v1.Z * v2.X - v1.X * v2.X, v1.X * v2.Y - v1.Y * v2.X);
        }
        
        //Du hade en rotationsfunktion redan så slipper skriva den : )
        #endregion

        #region Operators
        public static Vector3 operator +(Vector3 v1, Vector3 v2)
        {
            return Add(v1, v2);
        }
        public static Vector3 operator -(Vector3 v1, Vector3 v2)
        {
            return Subtract(v1, v2);
        }
        public static Vector3 operator *(Vector3 v, double scalar)
        {
            return Scale(v, scalar);
        }
        public static Vector3 operator *(double scalar, Vector3 v)
        {
            return Scale(v, scalar);
        }
        public static Vector3 operator /(Vector3 v, double scalar)
        {
            return Scale(v, 1 / scalar);
        }
        public static Vector3 operator /(double scalar, Vector3 v)
        {
            return Scale(v, 1 / scalar);
        }
        public static double operator *(Vector3 v1, Vector3 v2)
        {
            return DotProduct(v1, v2);
        }

        #endregion
    }
}